#ifndef CIOPS_OPERATION_H
#define CIOPS_OPERATION_H

#include <vector>

#include <QtGui>

#include "OperationParam.h"
#include "../Core/Point2D.h"
#include "../View/View.h"
#include "../View/Scene.h"

namespace CIView {
    class View;
}

namespace CIOps {
    /**
     * Abstract class that represents the base class for 
     * all executable operations in the application     
     **/
    class Operation {    
        //Friend Classes
        friend class OperationManager;
        friend class CIView::View;

    public:            
        Operation (std::vector<CIView::View*>& v);      //Constructor
        virtual ~Operation();                           //Destructor

        //Possible operation status
        enum {
            INITIAL                 //Initial status
          , WAITING_FOR_EVENTS      //The execution is locked to wait some event
          , STEP_COMPLETED          //Operation step executed corretly               
          , COMPLETED               //Operation executed corretly               
          , UNDO                    //Operation executed an undo
          , EXCEPTION               //Operation exception
          , ZOMBIE                  //Operation finished without producing useful results
        };        

    private:        
        unsigned int oldSelectionMode;                  //The old selection mode
        std::vector< std::vector<bool> > oldSelection;  //Vectors used to keep track of the previously selected vertices
        std::vector< std::vector<bool> > newSelection;  //Vectors used to keep track of selected vertices


        bool SaveVerticesSelectionStatus (std::vector< std::vector<bool> >& status);//Method called to save the vertices selection status 
        
        void SetVerticesSelectionStatus (std::vector< std::vector<bool> >& status); //Method called to set the vertices selection status
        void SetFacesSelectionStatus (std::vector< std::vector<bool> >& status);    //Method called to set the faces selection status                

        void SetVisibilityStatus (std::vector< std::vector<bool> >& status);        //Method called to set the visibility status                

    protected:
        std::vector<CIView::View*>& views;              //The 3D views
        CIView::Scene& scene;                           //A reference to the 3D scene
        std::vector<OperationParam*> parameters;        //The operation parameters
        int status;                                     //The operation status

        unsigned int newSelectionMode;                  //The new selection mode

        //Utility Protected Methods        
        bool SaveOldSelection();                        //Method called to save old selection status
        bool SaveNewSelection();                        //Method called to save the new selection status
        void RestoreOldSelection();                     //Method called to restore the old selection status 
        void RestoreNewSelection();                     //Method called to restore the new selection 

        void RestoreOldVisibility();                    //Method called to restore the old visibility of the primitives

        void RestoreFeedbackPosition();                 //Method called to restore the feedback position

        void UpdateViews();             //Method called to updates the 3D views

    public:            
        //Utility Methods
        virtual int Exec() = 0;         //Method called to execute directly the operation
        virtual void Undo() = 0;        //Method called to undo the operation
        virtual void Redo() = 0;        //Method called to redo the operation

        virtual void MousePressEvent (CIView::View* view, QMouseEvent* e) = 0;        //Mouse Pressed event handler
        virtual void MouseReleaseEvent (CIView::View* view, QMouseEvent* e) = 0;      //Mouse Released event handler
        virtual void MouseMoveEvent (CIView::View* view, QMouseEvent* e) = 0;         //Mouse Moved event handler
        virtual void WheelEvent (CIView::View* view, QWheelEvent* e) = 0;             //Wheel event handler

        //Methods called to add parameterd for this operation
        void AddParameter (OperationParam* param);
        void AddParameter (std::string& name, OperationParam::ParamType type, std::string& value, std::string& example, bool required);

    };
}

#endif /* CIOPS_OPERATION_H */
